package service

import (
	"sync"
)

// TaskManager 协程池实现
type TaskManager struct {
	jobs     chan func()    // 任务队列（缓存区），存放待执行的任务函数
	stop     chan struct{}  // 停止信号，用于通知所有 worker 退出
	stopOnce sync.Once      // 确保 Shutdown() 只执行一次，防止重复关闭
	wg       sync.WaitGroup // 等待 worker 全部退出的计数器
}

var manager *TaskManager // 全局唯一实例
var once sync.Once

// GetTaskManager 获取全局唯一的 TaskManager（单例） 初始化时会创建指定数量的 worker 并启动任务队列
func GetTaskManager() *TaskManager {
	once.Do(func() {
		manager = newTaskManager(taskManagerPoolSize, taskQueueSize)
	})
	return manager
}

// newTaskManager 创建一个 TaskManager 实例并启动指定数量的 worker 协程
func newTaskManager(workerCount, queueSize int) *TaskManager {
	tm := &TaskManager{
		jobs: make(chan func(), queueSize), // 带缓冲的任务通道
		stop: make(chan struct{}),          // 停止信号通道
	}
	tm.startWorkers(workerCount)
	return tm
}

// startWorkers 启动给定数量的 worker 协程 每个 worker 从 jobs 队列中取任务并执行，直到收到 stop 或 jobs 关闭信号退出
func (m *TaskManager) startWorkers(count int) {
	for i := 0; i < count; i++ {
		m.wg.Add(1) // 增加活跃 worker 计数
		go func() {
			defer m.wg.Done() // worker 退出时计数减一
			for {
				select {
				case job, ok := <-m.jobs: // 从任务队列取任务
					if !ok {
						return
					}
					if job != nil {
						job() // 执行任务
					}
				case <-m.stop:
					// 收到停止信号，退出 worker
					return
				}
			}
		}()
	}
}

// RunTask 提交任务到任务队列，等待空闲 worker 执行 如果 TaskManager 已经关闭或任务为空，则直接忽略
func (m *TaskManager) RunTask(task func()) {
	if task == nil {
		return
	}
	select {
	case <-m.stop:
		// 已关闭，不再接收新任务
		return
	case m.jobs <- task:
		// 提交任务到队列，可能立即被 worker 执行
	}
}

// Shutdown 关闭 TaskManager
// - 关闭停止信号和任务队列
// - 等待所有 worker 执行完手头任务并退出
func (m *TaskManager) Shutdown() {
	m.stopOnce.Do(func() {
		close(m.stop) // 发送停止信号给所有 worker
		close(m.jobs) // 关闭任务队列（阻止新任务并让阻塞的 worker 退出）
		m.wg.Wait()   // 等待全部 worker 完成任务并退出
	})
}
